import {createNamespace} from '../utils';
import {range} from '../utils/format/number';
import {preventDefault} from '../utils/dom/event';
import {TouchMixin} from '../mixins/touch';
import {ClickOutsideMixin} from '../mixins/click-outside';

var _createNamespace = createNamespace('swipe-cell'),
    createComponent = _createNamespace[0],
    bem = _createNamespace[1];

var THRESHOLD = 0.15;
export default createComponent({
    mixins: [TouchMixin, ClickOutsideMixin({
        event: 'touchstart',
        method: 'onClick'
    })],
    props: {
        // @deprecated
        // should be removed in next major version, use beforeClose instead
        onClose: Function,
        beforeClose: Function,
        disabled: Boolean,
        leftWidth: Number,
        rightWidth: Number,
        stopPropagation: Boolean,
        name: {
            type: [Number, String],
            default: ''
        }
    },
    data: function data() {
        return {
            offset: 0,
            dragging: false
        };
    },
    computed: {
        computedLeftWidth: function computedLeftWidth() {
            return this.leftWidth || this.getWidthByRef('left');
        },
        computedRightWidth: function computedRightWidth() {
            return this.rightWidth || this.getWidthByRef('right');
        }
    },
    mounted: function mounted() {
        this.bindTouchEvent(this.$el);
    },
    methods: {
        getWidthByRef: function getWidthByRef(ref) {
            if (this.$refs[ref]) {
                var rect = this.$refs[ref].getBoundingClientRect();
                return rect.width;
            }

            return 0;
        },
        // @exposed-api
        open: function open(position) {
            var offset = position === 'left' ? this.computedLeftWidth : -this.computedRightWidth;
            this.opened = true;
            this.offset = offset;
            this.$emit('open', {
                position: position,
                name: this.name,
                // @deprecated
                // should be removed in next major version
                detail: this.name
            });
        },
        // @exposed-api
        close: function close(position) {
            this.offset = 0;

            if (this.opened) {
                this.opened = false;
                this.$emit('close', {
                    position: position,
                    name: this.name
                });
            }
        },
        onTouchStart: function onTouchStart(event) {
            if (this.disabled) {
                return;
            }

            this.startOffset = this.offset;
            this.touchStart(event);
        },
        onTouchMove: function onTouchMove(event) {
            if (this.disabled) {
                return;
            }

            this.touchMove(event);

            if (this.direction === 'horizontal') {
                this.dragging = true;
                this.lockClick = true;
                var isPrevent = !this.opened || this.deltaX * this.startOffset < 0;

                if (isPrevent) {
                    preventDefault(event, this.stopPropagation);
                }

                this.offset = range(this.deltaX + this.startOffset, -this.computedRightWidth, this.computedLeftWidth);
            }
        },
        onTouchEnd: function onTouchEnd() {
            var _this = this;

            if (this.disabled) {
                return;
            }

            if (this.dragging) {
                this.toggle(this.offset > 0 ? 'left' : 'right');
                this.dragging = false; // compatible with desktop scenario

                setTimeout(function () {
                    _this.lockClick = false;
                }, 0);
            }
        },
        toggle: function toggle(direction) {
            var offset = Math.abs(this.offset);
            var threshold = this.opened ? 1 - THRESHOLD : THRESHOLD;
            var computedLeftWidth = this.computedLeftWidth,
                computedRightWidth = this.computedRightWidth;

            if (computedRightWidth && direction === 'right' && offset > computedRightWidth * threshold) {
                this.open('right');
            } else if (computedLeftWidth && direction === 'left' && offset > computedLeftWidth * threshold) {
                this.open('left');
            } else {
                this.close();
            }
        },
        onClick: function onClick(position) {
            if (position === void 0) {
                position = 'outside';
            }

            this.$emit('click', position);

            if (this.opened && !this.lockClick) {
                if (this.beforeClose) {
                    this.beforeClose({
                        position: position,
                        name: this.name,
                        instance: this
                    });
                } else if (this.onClose) {
                    this.onClose(position, this, {
                        name: this.name
                    });
                } else {
                    this.close(position);
                }
            }
        },
        getClickHandler: function getClickHandler(position, stop) {
            var _this2 = this;

            return function (event) {
                if (stop) {
                    event.stopPropagation();
                }

                _this2.onClick(position);
            };
        },
        genLeftPart: function genLeftPart() {
            var h = this.$createElement;
            var content = this.slots('left');

            if (content) {
                return h("div", {
                    "ref": "left",
                    "class": bem('left'),
                    "on": {
                        "click": this.getClickHandler('left', true)
                    }
                }, [content]);
            }
        },
        genRightPart: function genRightPart() {
            var h = this.$createElement;
            var content = this.slots('right');

            if (content) {
                return h("div", {
                    "ref": "right",
                    "class": bem('right'),
                    "on": {
                        "click": this.getClickHandler('right', true)
                    }
                }, [content]);
            }
        }
    },
    render: function render() {
        var h = arguments[0];
        var wrapperStyle = {
            transform: "translate3d(" + this.offset + "px, 0, 0)",
            transitionDuration: this.dragging ? '0s' : '.6s'
        };
        return h("div", {
            "class": bem(),
            "on": {
                "click": this.getClickHandler('cell')
            }
        }, [h("div", {
            "class": bem('wrapper'),
            "style": wrapperStyle
        }, [this.genLeftPart(), this.slots(), this.genRightPart()])]);
    }
});